//
//  AliMNSRequest.m
//  AlibabaCloudMNSiOS
//
//  Created by David Chen on 28/03/2017.
//  Copyright © 2017 AliCloud. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "AliMNSRequest.h"
#import "AliMNSCommon.h"
#import "AliMNSHttpBodyEncoder.h"

@implementation AliMNSRequestBase

@synthesize method;
@synthesize requestId;

-(AliMNSHttpRequestInternal*) buildInternalHttpRequest:(AliMNSClient*) mnsClient
{
    AliMNSHttpRequestInternal* internalReq = [AliMNSHttpRequestInternal new];
    internalReq.header = [NSMutableDictionary new];
    internalReq.method = method;

    [self buildUri:internalReq];

    //build data
    [self buildData:internalReq];

    //build header
    [self buildHeader:self withInternalReq: internalReq withMNSClient: mnsClient];

    return internalReq;
}

-(void)buildUri:(AliMNSHttpRequestInternal*) internalReq
{
    // do nothing.
}

-(void)buildData:(AliMNSHttpRequestInternal*) internalReq
{
    // set empty body.
    internalReq.data = NULL;
}

-(void)buildHeader:(AliMNSRequestBase*) req
   withInternalReq:(AliMNSHttpRequestInternal*) reqInternal
     withMNSClient:(AliMNSClient*) mnsClient
{
    if (req.requestId != NULL)
    {
        [reqInternal.header setValue:req.requestId forKey:@"x-mns-user-request-id"];
    }
    if(mnsClient.http.keepAlive)
    {
        [reqInternal.header setValue:@"Keep-Alive" forKey:@"Connection"];
    }
    if(reqInternal.data != NULL)
    {
        [reqInternal.header setValue:[AliMNSCommon base64Md5ForData:reqInternal.data] forKey:
         @"content-md5"];
        [reqInternal.header setValue: @"text/xml;charset=UTF-8" forKey:@"content-type"];
    }
    [reqInternal.header setValue:[AliMNSCommon getDateString:[AliMNSCommon getInstance].DATE_FORMATTOR withTimezone:@"GMT"] forKey:@"date"];
    [reqInternal.header setValue:mnsClient.version forKey:@"x-mns-version"];
    //[reqInternal.header setValue:mnsClient.host forKey: @"host"];
    [reqInternal.header setValue:@"alicloud-ios-sdk" forKey:@"user-agent"];

    NSString* authStr = [AliMNSCommon getSignature:reqInternal.header withMethod:req.method withURI: reqInternal.uri withAccessId:mnsClient.accessId withAccessKey:mnsClient.accessKey];
    [reqInternal.header setValue: authStr forKey:@"Authorization"];

    if(mnsClient.securityToken != NULL)
    {
        [reqInternal.header setValue:mnsClient.securityToken forKey:@"security-token"];
    }
}

@end

/*
 Queue related operations
 */

/* AliMNSCreateQueueRequest */
@implementation AliMNSCreateQueueRequest

@synthesize queueName;
@synthesize visibilityTimeout;
@synthesize maximumMessageSize;
@synthesize messageRetentionPeriod;
@synthesize delaySeconds;
@synthesize pollingWaitSeconds;
@synthesize loggingEnable;

-(id)initWithQueueName:(NSString*) qName
{
    queueName = qName;

    // set default values.
    visibilityTimeout = -1;
    maximumMessageSize = -1;
    messageRetentionPeriod = -1;
    delaySeconds = -1;
    pollingWaitSeconds = -1;
    loggingEnable = -1;

    super.method = @"PUT";
    return self;
}

-(void) setPropertiesFromQueueMeta:(AliMNSQueueMeta*) qMeta
{
    visibilityTimeout = qMeta.visibilityTimeout;
    maximumMessageSize = qMeta.maximumMessageSize;
    messageRetentionPeriod = qMeta.messageRetentionPeriod;
    delaySeconds = qMeta.delaySeconds;
    pollingWaitSeconds = qMeta.pollingWaitSeconds;
    loggingEnable = qMeta.loggingEnable;
}

-(void)buildUri:(AliMNSHttpRequestInternal*) internalReq
{
    internalReq.uri = [NSString stringWithFormat:@"/%@/%@",
                       [AliMNSCommon getInstance].QUEUES, queueName];
}

-(void)buildData:(AliMNSHttpRequestInternal*) reqInternal
{
    NSMutableDictionary* dataDict = [NSMutableDictionary new];
    [AliMNSHttpBodyEncoder addNodeIfValid:@"VisibilityTimeout" withNodeValue: [NSString stringWithFormat:@"%ld", (long)self.visibilityTimeout] withInvalidValue:@"-1"
        withDataDict: dataDict];
    [AliMNSHttpBodyEncoder addNodeIfValid:@"MaximumMessageSize" withNodeValue: [NSString stringWithFormat:@"%ld", (long)self.maximumMessageSize] withInvalidValue:@"-1" withDataDict: dataDict];
    [AliMNSHttpBodyEncoder addNodeIfValid:@"MessageRetentionPeriod" withNodeValue: [NSString stringWithFormat:@"%ld", (long)self.messageRetentionPeriod] withInvalidValue:@"-1" withDataDict: dataDict];
    [AliMNSHttpBodyEncoder addNodeIfValid:@"DelaySeconds" withNodeValue: [NSString stringWithFormat:@"%ld", (long)self.delaySeconds] withInvalidValue:@"-1" withDataDict: dataDict];
    [AliMNSHttpBodyEncoder addNodeIfValid:@"PollingWaitSeconds" withNodeValue: [NSString stringWithFormat:@"%ld", (long)self.pollingWaitSeconds] withInvalidValue:@"-1" withDataDict: dataDict];

    NSString* tmpLogginEnable = nil;
    if(self.loggingEnable == 0 )
    {
        tmpLogginEnable = @"False";
    }
    if(self.loggingEnable == 1)
    {
        tmpLogginEnable = @"True";
    }
    if (tmpLogginEnable != nil)
    {
        [AliMNSHttpBodyEncoder addNodeIfValid:@"LoggingEnabled" withNodeValue: tmpLogginEnable withInvalidValue:NULL withDataDict: dataDict];
    }

    NSString* data = [AliMNSHttpBodyEncoder encodeDict:@"Queue" withDataDict: dataDict];
    reqInternal.data = [data dataUsingEncoding:NSUTF8StringEncoding];
}

@end

/* AliMNSDeleteQueueRequest */
@implementation AliMNSDeleteQueueRequest
@synthesize queueName;

-(id)initWithQueueName:(NSString*) qName
{
    queueName = qName;
    super.method = @"DELETE";
    return self;
}

-(void)buildUri:(AliMNSHttpRequestInternal*) internalReq
{
    internalReq.uri = [NSString stringWithFormat:@"/%@/%@",
                       [AliMNSCommon getInstance].QUEUES, queueName];
}
@end

/* AliMNSListQueueRequest */
@implementation AliMNSListQueueRequest
@synthesize prefix;
@synthesize returnNumber;
@synthesize marker;

-(id)initWithPrefix:(NSString*)pPrefix
   withReturnNumber:(NSInteger)pReturnNumber
         withMarker:(NSString*)pMarker
{
    prefix = pPrefix;
    returnNumber = pReturnNumber;
    marker = pMarker;
    super.method = @"GET";
    return self;
}

-(void)buildUri:(AliMNSHttpRequestInternal*) internalReq
{
    internalReq.uri = [NSString stringWithFormat:@"/%@", [AliMNSCommon getInstance].QUEUES];

    if (prefix != nil && ![prefix isEqual: @""])
    {
        [internalReq.header setValue: prefix forKey:@"x-mns-prefix"];
    }
    if (returnNumber > 0)
    {
        [internalReq.header setValue: [NSString stringWithFormat:@"%ld", (long)returnNumber] forKey:@"x-mns-ret-number"];
    }
    if (marker != nil && ![marker isEqual: @""])
    {
        [internalReq.header setValue: marker forKey:@"x-mns-marker"];
    }
}
@end

/* AliMNSSetQueueAttributesRequest */
@implementation AliMNSSetQueueAttributesRequest

@synthesize queueName;
@synthesize messageRetentionPeriod;
@synthesize maximumMessageSize;
@synthesize delaySeconds;
@synthesize visibilityTimeout;

-(id)initWithQueueName:(NSString*)qName
{
    queueName = qName;
    messageRetentionPeriod = -1;
    maximumMessageSize = -1;
    delaySeconds = -1;
    visibilityTimeout = -1;
    super.method = @"PUT";
    return self;
}

-(void)buildUri:(AliMNSHttpRequestInternal*) internalReq
{
    internalReq.uri = [NSString stringWithFormat:@"/%@/%@?metaoverride=true",
                       [AliMNSCommon getInstance].QUEUES, queueName];
}

-(void)buildData:(AliMNSHttpRequestInternal*) reqInternal
{
    NSMutableDictionary* dataDict = [NSMutableDictionary new];
    [AliMNSHttpBodyEncoder addNodeIfValid:@"VisibilityTimeout" withNodeValue: [NSString stringWithFormat:@"%ld", (long)self.visibilityTimeout] withInvalidValue:@"-1"
                             withDataDict: dataDict];
    [AliMNSHttpBodyEncoder addNodeIfValid:@"MaximumMessageSize" withNodeValue: [NSString stringWithFormat:@"%ld", (long)self.maximumMessageSize] withInvalidValue:@"-1" withDataDict: dataDict];
    [AliMNSHttpBodyEncoder addNodeIfValid:@"MessageRetentionPeriod" withNodeValue: [NSString stringWithFormat:@"%ld", (long)self.messageRetentionPeriod] withInvalidValue:@"-1" withDataDict: dataDict];
    [AliMNSHttpBodyEncoder addNodeIfValid:@"DelaySeconds" withNodeValue: [NSString stringWithFormat:@"%ld", (long)self.delaySeconds] withInvalidValue:@"-1" withDataDict: dataDict];

    NSString* data = [AliMNSHttpBodyEncoder encodeDict:@"Queue" withDataDict: dataDict];
    reqInternal.data = [data dataUsingEncoding:NSUTF8StringEncoding];
}

@end


/* AliMNSGetQueueAttributesRequest */
@implementation AliMNSGetQueueAttributesRequest

@synthesize queueName;

-(id)initWithQueueName:(NSString*)qName
{
    queueName = qName;
    super.method = @"GET";
    return self;
}

-(void)buildUri:(AliMNSHttpRequestInternal*) internalReq
{
    internalReq.uri = [NSString stringWithFormat:@"/%@/%@",
                       [AliMNSCommon getInstance].QUEUES, queueName];
}
@end

/* AliMNSSendMessageRequest */
@implementation AliMNSSendMessageRequest
@synthesize queueName;
@synthesize messageBody;
@synthesize delaySeconds;
@synthesize base64Encode;
@synthesize priority;

-(id) initWithQueueName:(NSString*)qName
        withMessageBody:(NSString*)mBody
{
    queueName = qName;
    messageBody = mBody;

    //set other members with default values.
    delaySeconds = -1;
    base64Encode = false;
    priority = -1;
    super.method = @"POST";
    return self;
}

-(void)buildUri:(AliMNSHttpRequestInternal*) internalReq
{
    internalReq.uri = [NSString stringWithFormat:@"/%@/%@/messages",
                       [AliMNSCommon getInstance].QUEUES, queueName];
}

-(void)buildData:(AliMNSHttpRequestInternal*) reqInternal
{
    NSMutableDictionary* dataDict = [NSMutableDictionary new];
    [AliMNSHttpBodyEncoder addNodeIfValid:@"MessageBody" withNodeValue: self.messageBody withInvalidValue:nil withDataDict: dataDict];
    [AliMNSHttpBodyEncoder addNodeIfValid:@"DelaySeconds" withNodeValue: [NSString stringWithFormat:@"%ld", (long)self.delaySeconds] withInvalidValue:@"-1" withDataDict: dataDict];
    [AliMNSHttpBodyEncoder addNodeIfValid:@"Priority" withNodeValue: [NSString stringWithFormat:@"%ld", (long)self.priority] withInvalidValue:@"-1" withDataDict: dataDict];

    NSString* data = [AliMNSHttpBodyEncoder encodeDict:@"Message" withDataDict: dataDict];
    reqInternal.data = [data dataUsingEncoding:NSUTF8StringEncoding];
}

@end

/* AliMNSBatchSendMessageRequest */
@implementation AliMNSBatchSendMessageRequest
@synthesize queueName;
@synthesize messageList;
@synthesize base64Encode;

-(id) initWithQueueName:(NSString*)qName
        withMessageList:(NSArray*)msgList
{
    queueName = qName;
    messageList = msgList;

    base64Encode = false;
    super.method = @"POST";
    return self;
}

-(void)buildUri:(AliMNSHttpRequestInternal*) internalReq
{
    internalReq.uri = [NSString stringWithFormat:@"/%@/%@/messages",
                       [AliMNSCommon getInstance].QUEUES, queueName];
}

-(void)buildData:(AliMNSHttpRequestInternal*) reqInternal
{
    NSUInteger count = [messageList count];
    NSMutableArray* dataList = [NSMutableArray new];
    for (int i = 0; i < count; i++)
    {
        AliMNSMessage* msg = [messageList objectAtIndex:i];
        NSMutableDictionary* msgDict = [NSMutableDictionary new];
        [AliMNSHttpBodyEncoder addNodeIfValid:@"MessageBody" withNodeValue: msg.messageBody withInvalidValue:nil withDataDict: msgDict];
        [AliMNSHttpBodyEncoder addNodeIfValid:@"DelaySeconds" withNodeValue: [NSString stringWithFormat:@"%ld", (long)msg.delaySeconds] withInvalidValue:@"-1" withDataDict: msgDict];
        [AliMNSHttpBodyEncoder addNodeIfValid:@"Priority" withNodeValue: [NSString stringWithFormat:@"%ld", (long)msg.priority] withInvalidValue:@"-1" withDataDict: msgDict];

        [dataList addObject:msgDict];
    }

    NSString* data = [AliMNSHttpBodyEncoder encodeList:@"Messages" withSedNodeName: @"Message"withDataList: dataList];
    reqInternal.data = [data dataUsingEncoding:NSUTF8StringEncoding];
}

@end

/* AliMNSPeekMessageRequest */
@implementation AliMNSPeekMessageRequest
@synthesize queueName;
@synthesize base64Encode;
-(id) initWithQueueName:(NSString*)qName
{
    queueName = qName;

    base64Encode = false;
    super.method = @"GET";
    return self;
}

-(void)buildUri:(AliMNSHttpRequestInternal*) internalReq
{
    internalReq.uri = [NSString stringWithFormat:@"/%@/%@/messages?peekonly=true",
                       [AliMNSCommon getInstance].QUEUES, queueName];
}

@end

/* AliMNSBatchPeekMessageRequest */
@implementation AliMNSBatchPeekMessageRequest
@synthesize queueName;
@synthesize numOfMessages;
@synthesize base64Encode;

-(id) initWithQueueName:(NSString*)qName
      withNumOfMessages:(NSInteger)num
{
    queueName = qName;
    numOfMessages = num;
    base64Encode = false;
    super.method = @"GET";
    return self;
}

-(void)buildUri:(AliMNSHttpRequestInternal*) internalReq
{
    internalReq.uri = [NSString stringWithFormat:@"/%@/%@/messages?peekonly=true&numOfMessages=%ld",
                       [AliMNSCommon getInstance].QUEUES, queueName,numOfMessages];
}
@end

/* AliMNSReceiveMessageRequest */
@implementation AliMNSReceiveMessageRequest
@synthesize queueName;
@synthesize waitSeconds;

-(id) initWithQueueName:(NSString*)qName
{
    queueName = qName;

    waitSeconds = -1;
    super.method = @"GET";
    return self;
}

-(void)buildUri:(AliMNSHttpRequestInternal*) internalReq
{
    if (waitSeconds > 0 && waitSeconds <= 30)
    {
        internalReq.uri = [NSString stringWithFormat:@"/%@/%@/messages?waitseconds=%ld",
                           [AliMNSCommon getInstance].QUEUES, queueName, waitSeconds];
    }
    else
    {
        internalReq.uri = [NSString stringWithFormat:@"/%@/%@/messages",
                           [AliMNSCommon getInstance].QUEUES, queueName];
    }
}

@end

/* AliMNSBatchReceiveMessageRequest */
@implementation AliMNSBatchReceiveMessageRequest
@synthesize queueName;
@synthesize waitSeconds;
@synthesize numOfMessages;

-(id) initWithQueueName:(NSString*)qName
      withNumOfMessages:(NSInteger)batchSize
{
    queueName = qName;
    numOfMessages = batchSize;
    waitSeconds = -1;
    super.method = @"GET";
    return self;
}

-(void)buildUri:(AliMNSHttpRequestInternal*) internalReq
{
    if (waitSeconds > 0 && waitSeconds <= 30)
    {
        internalReq.uri = [NSString stringWithFormat:@"/%@/%@/messages?numOfMessages=%ld&waitseconds=%ld",
                           [AliMNSCommon getInstance].QUEUES, queueName,numOfMessages, waitSeconds];
    }
    else
    {
        internalReq.uri = [NSString stringWithFormat:@"/%@/%@/messages?numOfMessages=%ld",
                           [AliMNSCommon getInstance].QUEUES, queueName,numOfMessages];
    }
}

@end

/* AliMNSDeleteMessageRequest */
@implementation AliMNSDeleteMessageRequest
@synthesize queueName;
@synthesize receiptHandle;


-(id) initWithQueueName:(NSString*)qName
      withReceiptHandle:(NSString*)rHandle
{
    queueName = qName;
    receiptHandle = rHandle;

    super.method = @"DELETE";
    return self;
}

-(void)buildUri:(AliMNSHttpRequestInternal*) internalReq
{
    internalReq.uri = [NSString stringWithFormat:@"/%@/%@/messages?ReceiptHandle=%@",
                       [AliMNSCommon getInstance].QUEUES, queueName, receiptHandle];
}
@end

/* AliMNSBatchDeleteMessageRequest */
@implementation AliMNSBatchDeleteMessageRequest
@synthesize receiptHandleList;
@synthesize queueName;

-(id) initWithQueueName:(NSString*) qName
  withReceiptHandleList:(NSArray*) rHanldeList
{
    queueName = qName;
    receiptHandleList = rHanldeList;

    super.method = @"DELETE";
    return self;
}

-(void)buildUri:(AliMNSHttpRequestInternal*) internalReq
{
    internalReq.uri = [NSString stringWithFormat:@"/%@/%@/messages",
                       [AliMNSCommon getInstance].QUEUES, queueName];
}

-(void)buildData:(AliMNSHttpRequestInternal*) reqInternal
{
    NSString* data = [AliMNSHttpBodyEncoder encodeList:@"ReceiptHandles" withSedNodeName: @"ReceiptHandle" withDataList: receiptHandleList];
    reqInternal.data = [data dataUsingEncoding:NSUTF8StringEncoding];
}

@end

/* AliMNSChangeMessageVisibilityRequest */
@implementation AliMNSChangeMessageVisibilityRequest
@synthesize queueName;
@synthesize receiptHandle;
@synthesize visibilityTimeout;

-(id) initWithQueueName:(NSString*)qName
      withReceiptHandle:(NSString*)rHandle
  withVisibilityTimeout:(NSInteger)vTimeout
{
    queueName = qName;
    receiptHandle = rHandle;
    visibilityTimeout = vTimeout;
    super.method = @"PUT";
    return self;
}

-(void)buildUri:(AliMNSHttpRequestInternal*) internalReq
{
    internalReq.uri = [NSString stringWithFormat:@"/%@/%@/messages?receiptHandle=%@&visibilityTimeout=%ld",
                       [AliMNSCommon getInstance].QUEUES, queueName, receiptHandle, visibilityTimeout];
}

@end

/*
 Topic related operations
 */

/* AliMNSCreateTopicRequest */
@implementation AliMNSCreateTopicRequest
@synthesize topicName;
@synthesize maximumMessageSize;
@synthesize loggingEnable;

-(id) initWithTopicName:(NSString*) pTopicName
{
    topicName = pTopicName;

    maximumMessageSize = -1;
    loggingEnable = -1;
    super.method = @"PUT";
    return self;
}

-(void)buildUri:(AliMNSHttpRequestInternal*) internalReq
{
    internalReq.uri = [NSString stringWithFormat:@"/%@/%@",
                       [AliMNSCommon getInstance].TOPICS, topicName];
}

-(void)buildData:(AliMNSHttpRequestInternal*) reqInternal
{
    NSMutableDictionary* dataDict = [NSMutableDictionary new];

    [AliMNSHttpBodyEncoder addNodeIfValid:@"MaximumMessageSize" withNodeValue: [NSString stringWithFormat:@"%ld", (long)self.maximumMessageSize] withInvalidValue:@"-1" withDataDict: dataDict];

    NSString* tmpLogginEnable = nil;
    if(self.loggingEnable == 0 )
    {
        tmpLogginEnable = @"False";
    }
    if(self.loggingEnable == 1)
    {
        tmpLogginEnable = @"True";
    }
    if (tmpLogginEnable != nil)
    {
        [AliMNSHttpBodyEncoder addNodeIfValid:@"LoggingEnabled" withNodeValue: tmpLogginEnable withInvalidValue:NULL withDataDict: dataDict];
    }

    NSString* data = [AliMNSHttpBodyEncoder encodeDict:@"Topic" withDataDict: dataDict];
    reqInternal.data = [data dataUsingEncoding:NSUTF8StringEncoding];
}

@end

/* AliMNSDeleteTopicRequest */
@implementation AliMNSDeleteTopicRequest
@synthesize topicName;

-(id) initWithTopicName:(NSString *)pTopicName
{
    topicName = pTopicName;
    super.method = @"DELETE";
    return self;
}

-(void)buildUri:(AliMNSHttpRequestInternal*) internalReq
{
    internalReq.uri = [NSString stringWithFormat:@"/%@/%@",
                       [AliMNSCommon getInstance].TOPICS, topicName];
}

@end

/*AliMNSListTopicRequest*/
@implementation AliMNSListTopicRequest
@synthesize prefix;
@synthesize returnNumber;
@synthesize marker;

-(id) initWithPrefix:(NSString*) pPrefix
    withReturnNumber:(NSInteger)pReturnNumber
          withMarker:(NSString *) pMarker
{
    prefix = pPrefix;
    returnNumber = pReturnNumber;
    marker = pMarker;

    super.method = @"GET";
    return self;
}

-(void)buildUri:(AliMNSHttpRequestInternal*) internalReq
{
    internalReq.uri = [NSString stringWithFormat:@"/%@", [AliMNSCommon getInstance].TOPICS];
    if (prefix != nil && ![prefix isEqual: @""])
    {
        [internalReq.header setValue: prefix forKey:@"x-mns-prefix"];
    }
    if (returnNumber > 0)
    {
        [internalReq.header setValue: [NSString stringWithFormat:@"%ld", (long)returnNumber] forKey:@"x-mns-ret-number"];
    }
    if (marker != nil && ![marker isEqual: @""])
    {
        [internalReq.header setValue: marker forKey:@"x-mns-marker"];
    }
}
@end

/* AliMNSSetTopicAttributesRequest */
@implementation AliMNSSetTopicAttributesRequest
@synthesize topicName;
@synthesize maximumMessageSize;
@synthesize loggingEnable;

-(id) initWithTopicName:(NSString*) pTopicName
        withMessageSize:(NSInteger) pMessageSize

{
    topicName = pTopicName;
    maximumMessageSize = pMessageSize;

    loggingEnable = -1;
    super.method = @"PUT";

    return self;
}

-(void)buildUri:(AliMNSHttpRequestInternal*) internalReq
{
    internalReq.uri = [NSString stringWithFormat:@"/%@/%@?metaoverride=true",
                       [AliMNSCommon getInstance].TOPICS, topicName];
}

-(void)buildData:(AliMNSHttpRequestInternal*) reqInternal
{
    NSMutableDictionary* dataDict = [NSMutableDictionary new];

    [AliMNSHttpBodyEncoder addNodeIfValid:@"MaximumMessageSize" withNodeValue: [NSString stringWithFormat:@"%ld", (long)self.maximumMessageSize] withInvalidValue:@"-1" withDataDict: dataDict];

    NSString* tmpLogginEnable = nil;
    if(self.loggingEnable == 0 )
    {
        tmpLogginEnable = @"False";
    }
    if(self.loggingEnable == 1)
    {
        tmpLogginEnable = @"True";
    }
    if (tmpLogginEnable != nil)
    {
        [AliMNSHttpBodyEncoder addNodeIfValid:@"LoggingEnabled" withNodeValue: tmpLogginEnable withInvalidValue:NULL withDataDict: dataDict];
    }

    NSString* data = [AliMNSHttpBodyEncoder encodeDict:@"Topic" withDataDict: dataDict];
    reqInternal.data = [data dataUsingEncoding:NSUTF8StringEncoding];
}

@end

/* AliMNSGetTopicAttributesRequest */
@implementation AliMNSGetTopicAttributesRequest
@synthesize topicName;

-(id) initWithTopicName:(NSString *)pTopicName
{
    topicName = pTopicName;

    super.method = @"GET";
    return self;
}

-(void)buildUri:(AliMNSHttpRequestInternal*) internalReq
{
    internalReq.uri = [NSString stringWithFormat:@"/%@/%@",
                       [AliMNSCommon getInstance].TOPICS, topicName];
}
@end

/* AliMNSPublishMessageRequest */
@implementation AliMNSPublishMessageRequest
@synthesize topicName;
@synthesize messageBody;
@synthesize messageTag;
@synthesize directSMS;
@synthesize directMail;

-(id) initWithTopicName:(NSString*) pTopicName
        withMessageBody:(NSString*) pMessageBody
         withMessageTag:(NSString*) pMessageTag
{
    topicName = pTopicName;
    messageBody = pMessageBody;
    messageTag = pMessageTag;

    directSMS = nil;
    directMail = nil;

    super.method = @"POST";
    return self;
}

-(void)buildUri:(AliMNSHttpRequestInternal*) internalReq
{
    internalReq.uri = [NSString stringWithFormat:@"/%@/%@/messages",
                       [AliMNSCommon getInstance].TOPICS, topicName];
}

-(void)buildData:(AliMNSHttpRequestInternal*) reqInternal
{
    NSMutableDictionary* dataDict = [NSMutableDictionary new];
    [AliMNSHttpBodyEncoder addNodeIfValid:@"MessageBody" withNodeValue: self.messageBody withInvalidValue:nil withDataDict: dataDict];

    [AliMNSHttpBodyEncoder addNodeIfValid:@"MessageTag" withNodeValue: self.messageTag withInvalidValue:nil withDataDict: dataDict];

    //todo: support for diretMail and directSMS.

    NSString* data = [AliMNSHttpBodyEncoder encodeDict:@"Message" withDataDict: dataDict];
    reqInternal.data = [data dataUsingEncoding:NSUTF8StringEncoding];
}

@end

/* AliMNSPublishMessageRequest */
@implementation AliMNSSubscribeRequest
@synthesize topicName;
@synthesize subscriptionName;
@synthesize endpointName;
@synthesize filterTag;
@synthesize notifyStrategy;
@synthesize notifyContentFormat;

-(id) initWithTopicName:(NSString*) pTopicName
   withSubscriptionName:(NSString*) pSubcriptionName
           withEndpoint:(NSString*) pEndpoint
{
    topicName = pTopicName;
    subscriptionName = pSubcriptionName;
    endpointName = pEndpoint;

    filterTag = nil;
    notifyStrategy = -1;
    notifyContentFormat = -1;

    super.method = @"PUT";

    return self;
}

-(void)buildUri:(AliMNSHttpRequestInternal*) internalReq
{
    internalReq.uri = [NSString stringWithFormat:@"/%@/%@/%@/%@",
                       [AliMNSCommon getInstance].TOPICS, topicName, [AliMNSCommon getInstance].SUBSCRIPTIONS, subscriptionName];
}


-(void)buildData:(AliMNSHttpRequestInternal*) reqInternal
{
    NSMutableDictionary* dataDict = [NSMutableDictionary new];

    [AliMNSHttpBodyEncoder addNodeIfValid:@"Endpoint" withNodeValue: endpointName withInvalidValue:nil withDataDict: dataDict];

    [AliMNSHttpBodyEncoder addNodeIfValid:@"FilterTag" withNodeValue: filterTag withInvalidValue:nil withDataDict: dataDict];

    if (notifyStrategy == ALIMNS_TOPIC_BACKOFF_RETRY)
    {
        [AliMNSHttpBodyEncoder addNodeIfValid:@"NotifyStrategy" withNodeValue: @"BACKOFF_RETRY" withInvalidValue:nil withDataDict: dataDict];
    }else if (notifyStrategy == ALIMNS_TOPIC_EXPONENTIAL_DECAY_RETRY)
    {
        [AliMNSHttpBodyEncoder addNodeIfValid:@"NotifyStrategy" withNodeValue: @"EXPONENTIAL_DECAY_RETRY" withInvalidValue:nil withDataDict: dataDict];
    }

    if (notifyContentFormat == ALIMNS_TOPIC_XML)
    {
        [AliMNSHttpBodyEncoder addNodeIfValid:@"NotifyContentFormat" withNodeValue: @"XML" withInvalidValue:nil withDataDict: dataDict];
    }else if (notifyContentFormat == ALIMNS_TOPIC_JSON)
    {
        [AliMNSHttpBodyEncoder addNodeIfValid:@"NotifyContentFormat" withNodeValue: @"JSON" withInvalidValue:nil withDataDict: dataDict];
    }else if (notifyContentFormat == ALIMNS_TOPIC_SIMPLIFIED)
    {
         [AliMNSHttpBodyEncoder addNodeIfValid:@"NotifyContentFormat" withNodeValue: @"SIMPLIFIED" withInvalidValue:nil withDataDict: dataDict];
    }

    NSString* data = [AliMNSHttpBodyEncoder encodeDict:@"Subscription" withDataDict: dataDict];
    reqInternal.data = [data dataUsingEncoding:NSUTF8StringEncoding];
}

@end

@implementation AliMNSUnsubcribeRequest
@synthesize topicName;
@synthesize subscriptionName;

-(id) initWithTopicName:(NSString*) pTopicName
   withSubscriptionName:(NSString *)pSubcriptionName
{
    topicName = pTopicName;
    subscriptionName = pSubcriptionName;

    super.method = @"DELETE";
    return self;
}

-(void)buildUri:(AliMNSHttpRequestInternal*) internalReq
{
    internalReq.uri = [NSString stringWithFormat:@"/%@/%@/%@/%@",
                       [AliMNSCommon getInstance].TOPICS, topicName, [AliMNSCommon getInstance].SUBSCRIPTIONS, subscriptionName];
}

@end

@implementation AliMNSListSubscriptionRequest
@synthesize topicName;
@synthesize prefix;
@synthesize returnNumber;
@synthesize marker;

-(id) initWithTopicName:(NSString*) pTopicName
{
    topicName = pTopicName;

    prefix = @"";
    returnNumber = -1;
    marker = @"";

    super.method = @"GET";
    return self;
}

-(void)buildUri:(AliMNSHttpRequestInternal*) internalReq
{
    internalReq.uri = [NSString stringWithFormat:@"/%@/%@/%@", [AliMNSCommon getInstance].TOPICS, topicName, [AliMNSCommon getInstance].SUBSCRIPTIONS];
    if (prefix != nil && ![prefix isEqual: @""])
    {
        [internalReq.header setValue: prefix forKey:@"x-mns-prefix"];
    }
    if (returnNumber > 0)
    {
        [internalReq.header setValue: [NSString stringWithFormat:@"%ld", (long)returnNumber] forKey:@"x-mns-ret-number"];
    }
    if (marker != nil && ![marker isEqual: @""])
    {
        [internalReq.header setValue: marker forKey:@"x-mns-marker"];
    }
}
@end

@implementation AliMNSSetSubscriptionAttributesRequest
@synthesize topicName;
@synthesize subscriptionName;
@synthesize notifyStrategy;

-(id) initWithTopicName:(NSString*) pTopicName
   withSubscriptionName:(NSString *)pSubcriptionName
{
    topicName = pTopicName;
    subscriptionName = pSubcriptionName;

    notifyStrategy = -1;

    super.method = @"PUT";
    return self;
}

-(void)buildUri:(AliMNSHttpRequestInternal*) internalReq
{
    internalReq.uri = [NSString stringWithFormat:@"/%@/%@/%@/%@?metaoverride=true",
                       [AliMNSCommon getInstance].TOPICS, topicName, [AliMNSCommon getInstance].SUBSCRIPTIONS, subscriptionName];
}

-(void)buildData:(AliMNSHttpRequestInternal*) reqInternal
{
    NSMutableDictionary* dataDict = [NSMutableDictionary new];

    if (notifyStrategy == ALIMNS_TOPIC_BACKOFF_RETRY)
    {
        [AliMNSHttpBodyEncoder addNodeIfValid:@"NotifyStrategy" withNodeValue: @"BACKOFF_RETRY" withInvalidValue:nil withDataDict: dataDict];
    }else if (notifyStrategy == ALIMNS_TOPIC_EXPONENTIAL_DECAY_RETRY)
    {
        [AliMNSHttpBodyEncoder addNodeIfValid:@"NotifyStrategy" withNodeValue: @"EXPONENTIAL_DECAY_RETRY" withInvalidValue:nil withDataDict: dataDict];
    }

    NSString* data = [AliMNSHttpBodyEncoder encodeDict:@"Subscription" withDataDict: dataDict];
    reqInternal.data = [data dataUsingEncoding:NSUTF8StringEncoding];
}

@end

@implementation AliMNSGetSubscriptionAttributesRequest
@synthesize topicName;
@synthesize subscriptionName;

-(id) initWithTopicName:(NSString*) pTopicName
   withSubscriptionName:(NSString *)pSubcriptionName
{
    topicName = pTopicName;
    subscriptionName = pSubcriptionName;

    super.method = @"GET";
    return self;
}

-(void)buildUri:(AliMNSHttpRequestInternal*) internalReq
{
    internalReq.uri = [NSString stringWithFormat:@"/%@/%@/%@/%@",
                       [AliMNSCommon getInstance].TOPICS, topicName, [AliMNSCommon getInstance].SUBSCRIPTIONS, subscriptionName];
}

@end
